package com.smartcommunity.elasticsearch.people;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.smartcommunity.base.common.CacheMap;
import com.smartcommunity.es.common.EsBasedataEnum;
import com.smartcommunity.es.common.EsRestUtils;
import com.smartcommunity.utils.DateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.smartcommunity.bean.constant.Constant;
import com.smartcommunity.bean.model.Pager;
import com.smartcommunity.elasticsearch.base.impl.BasedataDataService;
import com.smartcommunity.entity.people.EsPeopleEntity;
import com.smartcommunity.entity.people.People;
import com.smartcommunity.entity.vehicle.EsBaseVehEntity;
import com.smartcommunity.exception.BusinessException;

import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName 实有人口ES操作API
 * @Author yangyi
 * @Description TODO
 * @Date 2020/6/20 14:01
 * @Version 1.0
 */

@Component
@Slf4j
public class PeopleEsApi {
	
	@Autowired
	private BasedataDataService basedataDataService;
	@Autowired
	private EsRestUtils eSRestUtils;
	
	/**
	 * 新增或修改实有人口入库
	 * @param people
	 * @param isInsert
	 * @throws BusinessException
	 */
	public void saveOrUpdate(People people, boolean isInsert) throws BusinessException {
		if(people!=null) {
			EsPeopleEntity esPeople = EsPeopleEntity.parseFrom(people);
	        this.saveOrUpdate(esPeople, isInsert);
		}
	}
	
	/**
	 * 新增或修改实有人口入库
	 * @param esPeople
	 * @param isInsert
	 * @throws BusinessException
	 */
	public void saveOrUpdate(EsPeopleEntity esPeople, boolean isInsert) throws BusinessException {
		if(esPeople!=null) {
			if(esPeople.getMrowTime()==null) {
				esPeople.setMrowTime(DateUtils.getNowTimestamp());
			}
	        esPeople.setDataType(EsBasedataEnum.PEOPLE.getIntValue());
	        buildEsPeopleVillageCode(esPeople);
	        Map<String, String> peopleDataMap = new HashMap<String, String>();
	        //身份证号码有修改，先删除
			if(StringUtils.isNotEmpty(esPeople.getOldCredentialNo())){
				basedataDataService.deleteAndRefresh(basedataDataService.getIndexName(null), esPeople.getOldCredentialNo()+Constant.SEPARATOR+EsBasedataEnum.PEOPLE.getIntValue());
			}
			peopleDataMap.put(esPeople.getCredentialNo()+Constant.SEPARATOR+EsBasedataEnum.PEOPLE.getIntValue(), esPeople.toString());
	        basedataDataService.batchReplaceAndRefresh(basedataDataService.getIndexName(null), peopleDataMap);
	        if(!isInsert) {
	        	updateRelateVehicle(Collections.singletonList(esPeople));
	        }
		}
	}
	
	/**
	 * 批量新增或修改实有人口入库
	 * @param peopleList
	 * @param isInsert
	 * @throws BusinessException
	 */
	public void batchSaveOrUpdatePeople(List<People> peopleList, boolean isInsert) throws BusinessException {
		if(CollectionUtils.isNotEmpty(peopleList)) {
			List<EsPeopleEntity> esPeopleList = new ArrayList<EsPeopleEntity>();
			peopleList.forEach(people->{
				EsPeopleEntity esPeople = EsPeopleEntity.parseFrom(people);
		        esPeopleList.add(esPeople);
			});
			this.batchSaveOrUpdateEsPeople(esPeopleList, isInsert);
		}
	}
	
	/**
	 * 批量新增或修改实有人口入库
	 * @param esPeopleList
	 * @param isInsert
	 * @throws BusinessException
	 */
	public void batchSaveOrUpdateEsPeople(List<EsPeopleEntity> esPeopleList, boolean isInsert) throws BusinessException {
		if(CollectionUtils.isNotEmpty(esPeopleList)) {
			Map<String, String> peopleDataMap = new HashMap<String, String>();
			esPeopleList.forEach(esPeople->{
				if(esPeople.getMrowTime()==null) {
					esPeople.setMrowTime(DateUtils.getNowTimestamp());
				}
				esPeople.setDataType(EsBasedataEnum.PEOPLE.getIntValue());
		        buildEsPeopleVillageCode(esPeople);
		        peopleDataMap.put(esPeople.getCredentialNo()+Constant.SEPARATOR+EsBasedataEnum.PEOPLE.getIntValue(), esPeople.toString());
			});
	        basedataDataService.batchReplace(basedataDataService.getIndexName(null), peopleDataMap);
	        if(!isInsert) {
	        	updateRelateVehicle(esPeopleList);
	        }
		}
	}
	
	/**
	 * 修改实有人口部分属性
	 * @param credentialNo
	 * @param valueMap
	 * @throws BusinessException
	 */
	public void update(String credentialNo, Map<String, Object> valueMap) throws BusinessException {
		basedataDataService.update(basedataDataService.getIndexName(null), credentialNo+Constant.SEPARATOR+EsBasedataEnum.PEOPLE.getIntValue(), valueMap);
	}
	
	/**
	 * 批量修改实有人口部分属性
	 * @param map
	 * @throws BusinessException
	 */
	public void batchUpdate(Map<String, Map<String, Object>> map) throws BusinessException {
		basedataDataService.batchUpdate(basedataDataService.getIndexName(null), map);
	}
	
	/**
	 * 删除实有人口
	 * @param credentialNo
	 * @throws BusinessException
	 */
	public void delete(String credentialNo) throws BusinessException {
		//删除关联车辆
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("credentialNo.keyword", credentialNo));
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("dataType", EsBasedataEnum.VEHICLE.getIntValue()));
		basedataDataService.deleteQuery(basedataDataService.getIndexName(null), boolQueryBuilder);
		basedataDataService.deleteAndRefresh(basedataDataService.getIndexName(null), credentialNo+Constant.SEPARATOR+EsBasedataEnum.PEOPLE.getIntValue());
	}
	
	/**
	 * 批量删除实有人口
	 * @param noList
	 * @throws BusinessException
	 */
	public void batchDelete(List<String> noList) throws BusinessException {
		if(CollectionUtils.isNotEmpty(noList)) {
			noList.forEach(no->{
				this.delete(no);
			});
		}
	}
	
	/**
	 * 根据证件号码查询实有人口
	 * @param credentialNo
	 * @return
	 * @throws BusinessException
	 */
	public EsPeopleEntity getDataById(String credentialNo) throws BusinessException {
		String[] indexName = new String[] {basedataDataService.getIndexName(null)};
		List<Map<String, Object>> dataList = basedataDataService.getDataById(indexName, credentialNo+Constant.SEPARATOR+EsBasedataEnum.PEOPLE.getIntValue());
		if(CollectionUtils.isNotEmpty(dataList)) {
			return JSON.parseObject(JSON.toJSONString(dataList.get(0)), EsPeopleEntity.class);
		}
		return null;
	}
	
	/**
	 * 根据证件号码查询实有人口
	 * @param credentialNos
	 * @return
	 * @throws BusinessException
	 */
	public List<EsPeopleEntity> getDataByIds(List<String> credentialNos) throws BusinessException {
		String[] indexName = new String[] {basedataDataService.getIndexName(null)};
		List<EsPeopleEntity> result = new ArrayList<EsPeopleEntity>();
		List<String> esPeopleIds = new ArrayList<String>();
		if(CollectionUtils.isNotEmpty(credentialNos)) {
			for(String credentialNo:credentialNos) {
				if(StringUtils.isNotEmpty(credentialNo)) {
					esPeopleIds.add(credentialNo+Constant.SEPARATOR+EsBasedataEnum.PEOPLE.getIntValue());
				}
			}
		}
		if(CollectionUtils.isNotEmpty(esPeopleIds)) {
			List<Map<String, Object>> dataList = basedataDataService.getDataByIds(indexName, esPeopleIds);
			if(CollectionUtils.isNotEmpty(dataList)) {
				for(Map<String, Object> data:dataList) {
					EsPeopleEntity esPeopleEntity = JSON.parseObject(JSON.toJSONString(data), EsPeopleEntity.class);
					result.add(esPeopleEntity);
				}
			}
		}
		return result;
	}
	
	/**
	 * 补全实有人口的小区信息
	 * @param esPeople
	 */
	private void buildEsPeopleVillageCode(EsPeopleEntity esPeople) {
		List<String> villageCode = new ArrayList<String>();
		if (CollectionUtils.isNotEmpty(esPeople.getDetailAddress())) {
			esPeople.getDetailAddress().forEach(item -> {
				if(!villageCode.contains(item.getVillageCode())) {
					villageCode.add(item.getVillageCode());
				}
			});
		}
		esPeople.setVillageCode(villageCode);
	}
	
	/**
	 * 分页查询
	 * @throws BusinessException 
	 */
	public Pager<People> listPage(People people, int currentPage, int pageSize) throws BusinessException {
		//有图片的人口信息，放在前面显示
		return listPage(people, currentPage, pageSize, "idCardPic", "desc");
	}

	public Pager<People> listPage(People people, int currentPage, int pageSize, String sortField, String sortModel) throws BusinessException {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("dataType", EsBasedataEnum.PEOPLE.getIntValue()));
        if(StringUtils.isNotEmpty(people.getVillageCode())) {
        	boolQueryBuilder.must(QueryBuilders.termsQuery("villageCode", people.getVillageCode().replaceAll("'", "").split(",")));
        }
        //全文检索的条件配置
  		if (StringUtils.isNotEmpty(people.getText())) {
  			BoolQueryBuilder textQueryBuilder = QueryBuilders.boolQuery();
  			if (StringUtils.isBlank(people.getPeopleName())) {
  				textQueryBuilder.should(QueryBuilders.wildcardQuery("peopleName.keyword", "*"+people.getText()+"*"));   //姓名
  			}
  			if (StringUtils.isBlank(people.getCredentialNo())) {
  				textQueryBuilder.should(QueryBuilders.wildcardQuery("credentialNo.keyword", "*"+people.getText()+"*"));   //证件号码
  			}
  			if (StringUtils.isBlank(people.getPhoneNo())) {
  				textQueryBuilder.should(QueryBuilders.wildcardQuery("phoneNo.keyword", "*"+people.getText()+"*"));   //手机号码
  			}
  			boolQueryBuilder.must(textQueryBuilder);
  		}
  		log.info("分页查询es中的参数 residentiaType = {} ",people.getResidentiaType());
		if(people.getResidentiaType() != null) {
			boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("residentiaType", people.getResidentiaType()));
		}
        if(people.getPeopleType()!=null) {
        	boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("peopleType", people.getPeopleType()));   //人员类型
        }
        if(StringUtils.isNotEmpty(people.getCredentialNo())) {
        	boolQueryBuilder.must(QueryBuilders.wildcardQuery("credentialNo.keyword", "*"+people.getCredentialNo()+"*"));   //证件号码
        }
        if(StringUtils.isNotEmpty(people.getPhoneNo())) {
        	boolQueryBuilder.must(QueryBuilders.wildcardQuery("phoneNo.keyword", "*"+people.getPhoneNo()+"*"));    //手机号码
        }
        if(StringUtils.isNotEmpty(people.getMerge())) {
        	BoolQueryBuilder shouldQueryBuilder = QueryBuilders.boolQuery();
        	shouldQueryBuilder.should(QueryBuilders.wildcardQuery("credentialNo.keyword", "*"+people.getMerge()+"*"));    //证件号码
        	shouldQueryBuilder.should(QueryBuilders.wildcardQuery("phoneNo.keyword", "*"+people.getMerge()+"*"));    //手机号码
        	boolQueryBuilder.must(shouldQueryBuilder);
        }
        if(StringUtils.isNotEmpty(people.getPeopleName())) {
        	boolQueryBuilder.must(QueryBuilders.wildcardQuery("peopleName.keyword", "*"+people.getPeopleName()+"*"));   //姓名
        }
        if(StringUtils.isNotEmpty(people.getDomicileAddress())) {
        	boolQueryBuilder.must(QueryBuilders.wildcardQuery("domicileAddress.keyword", "*"+people.getDomicileAddress()+"*"));   //户籍地址
        }
		if(people.getGenderCode()!=null) {
			boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("genderCode", people.getGenderCode()));   //性别编码
		}
        if(StringUtils.isNotEmpty(people.getNation())) {
        	boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("nation.keyword", people.getNation()));    //民族
        }
        if(StringUtils.isNotEmpty(people.getBirthDateStart()) && StringUtils.isNotEmpty(people.getBirthDateEnd())) {      //年龄
        	boolQueryBuilder.must(QueryBuilders.rangeQuery("birthDate.keyword").from(people.getBirthDateStart()+"-01-01").to(people.getBirthDateEnd()+"-12-31"));
        }else if(StringUtils.isNotEmpty(people.getBirthDateStart())) {
        	boolQueryBuilder.must(QueryBuilders.rangeQuery("birthDate.keyword").from(people.getBirthDateStart()+"-01-01"));
        }else if(StringUtils.isNotEmpty(people.getBirthDateEnd())) {
        	boolQueryBuilder.must(QueryBuilders.rangeQuery("birthDate.keyword").to(people.getBirthDateEnd()+"-12-31"));
        }
        if(people.getIsVid()!=null) {
        	if(people.getIsVid().intValue()==1) {
        		boolQueryBuilder.must(QueryBuilders.existsQuery("vid"));       //是否已关联VID
        	}else if(people.getIsVid().intValue()==2) {
        		boolQueryBuilder.mustNot(QueryBuilders.existsQuery("vid"));
        	}
        }
        if(StringUtils.isNotEmpty(people.getIdCardPic())) {
        	if("1".equals(people.getIdCardPic())) {
        		boolQueryBuilder.must(QueryBuilders.existsQuery("idCardPic"));     //证件照
        	}else if("2".equals(people.getIdCardPic())) {
        		boolQueryBuilder.mustNot(QueryBuilders.existsQuery("idCardPic"));
        	}
        }
        if(StringUtils.isNotEmpty(people.getLabel())) {
        	boolQueryBuilder.must(QueryBuilders.termsQuery("lableList.id", people.getLabel().split(",")));     //标签
        }
        if(StringUtils.isNotEmpty(people.getVid())) {
        	boolQueryBuilder.must(QueryBuilders.termsQuery("vid", people.getVid().replaceAll("'", "").split(",")));   //VID
        }
        if(StringUtils.isNotEmpty(people.getFeatureId())) {
        	boolQueryBuilder.must(QueryBuilders.termsQuery("featureId", people.getFeatureId().replaceAll("'", "").split(",")));    //特征ID
        }
        if(StringUtils.isNotEmpty(people.getRemarks())) {
        	boolQueryBuilder.must(QueryBuilders.termsQuery("id", people.getRemarks().replaceAll("'", "").split(",")));     //id
        }
        if(people.getIsLeave()!=null) {
        	if(people.getIsLeave().intValue()==1) {
        		boolQueryBuilder.mustNot(QueryBuilders.matchPhraseQuery("detailAddress.move", 2));     //未迁出
        	}else if(people.getIsLeave().intValue()==2) {
        		boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("detailAddress.move", 2));     //已迁出
        	}
        }
        
        String[] indexName = new String[] {basedataDataService.getIndexName(null)};
        if (StringUtils.isEmpty(sortField)){
			sortField = "idCardPic";
			sortModel = "desc";
		}
		SortBuilder sortBuilder = eSRestUtils.builderSort(sortField, sortModel);
        Map<String, Object> result = basedataDataService.page(indexName, boolQueryBuilder, null, currentPage, pageSize, sortBuilder);
        if(result!=null && result.containsKey("total") && result.containsKey("rows")) {
	        int total = Integer.valueOf(result.get("total").toString());
	        List<Map<String, Object>> rows = (List<Map<String, Object>>) result.get("rows"); 
	        if (CollectionUtils.isNotEmpty(rows)) {
	            List<People> peopleList = new ArrayList<People>();
	            rows.forEach(item->{
	            	peopleList.add(JSON.parseObject(JSON.toJSONString(item), People.class));
	            });
	            return new Pager<People>(currentPage, pageSize, total, peopleList);
	        }
        }
        return new Pager<People>();
	}
	
	/**
	 * 更新实有人口关联的车辆
	 * @param esPeopleList
	 * @throws BusinessException 
	 */
	private void updateRelateVehicle(List<EsPeopleEntity> esPeopleList) throws BusinessException {
		if(CollectionUtils.isNotEmpty(esPeopleList)) {
			Map<String, String> vehicleDataMap = new HashMap<String, String>();
			List<Integer> peopleIds = new ArrayList<Integer>();
			Map<String, EsPeopleEntity> peopleMap = new HashMap<String, EsPeopleEntity>();
			for(EsPeopleEntity esPeople:esPeopleList) {
				if(esPeople.getId()!=null) {
					peopleIds.add(esPeople.getId());
					peopleMap.put(esPeople.getId().toString(), esPeople);
				}
			}
			if(CollectionUtils.isNotEmpty(peopleIds)) {
				BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		        boolQueryBuilder.must(QueryBuilders.termsQuery("peopleId", peopleIds));
		        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("dataType", EsBasedataEnum.VEHICLE.getIntValue()));
				SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
	    		searchSourceBuilder.size(Constant.SCROLL_SIZE); // 设定每次返回多少条数据
				List<Map<String, Object>> list = eSRestUtils.scrollQueryAll(basedataDataService.getIndexName(null), boolQueryBuilder, searchSourceBuilder);
				if(CollectionUtils.isNotEmpty(list)) {
					for(Map<String, Object> item:list) {
						EsBaseVehEntity esBaseVehEntity = JSON.parseObject(JSON.toJSONString(item), EsBaseVehEntity.class);
						if(esBaseVehEntity.getPeopleId()!=null && peopleMap.containsKey(esBaseVehEntity.getPeopleId().toString())) {
							EsPeopleEntity esPeople = peopleMap.get(esBaseVehEntity.getPeopleId().toString());
							esBaseVehEntity.setPeopleName(esPeople.getPeopleName());
							esBaseVehEntity.setCredentialNo(esPeople.getCredentialNo());
							esBaseVehEntity.setDetailAddress(esPeople.getDetailAddress());
							esBaseVehEntity.setVillageCode(esPeople.getVillageCode());
							esBaseVehEntity.setCredentialType(esPeople.getCredentialType());
							String credentialTypeCN = StringUtils.isNotEmpty(CacheMap.CREDENTIAL_TYPE_MAP.get(esPeople.getCredentialType())) ? CacheMap.CREDENTIAL_TYPE_MAP.get(esPeople.getCredentialType()) : "";
							esBaseVehEntity.setCredentialTypeCN(credentialTypeCN);
							esBaseVehEntity.setVillageCode(esPeople.getVillageCode());
							vehicleDataMap.put(esBaseVehEntity.getId()+Constant.SEPARATOR+EsBasedataEnum.VEHICLE.getIntValue(), esBaseVehEntity.toString());
						}
					}
				}
			}
			if(!org.springframework.util.CollectionUtils.isEmpty(vehicleDataMap)) {
				basedataDataService.batchReplace(basedataDataService.getIndexName(null), vehicleDataMap);
			}
		}
	}

}